package com.giw.uima.annotator;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.uima.SentenceAnnotation;
import org.apache.uima.TokenAnnotation;
import org.apache.uima.UimaContext;
import org.apache.uima.analysis_component.JCasAnnotator_ImplBase;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.cas.Type;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.tcas.Annotation;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.util.Level;

import com.giw.uima.ts.PersonAnnotation;
import com.giw.uima.ts.PlayerAnnotation;

public class PlayerAnnotator extends JCasAnnotator_ImplBase{

	private static final String WORD_PLAYER_PATH = "word_player";
	private static final String POS_FEATURENAME= "posTag";
	private Map<Integer,String> position2player;
	private List<String> player;
	private List<String> wordList;

	public void initialize(UimaContext aContext) throws ResourceInitializationException {
		this.position2player=new HashMap<Integer,String>();
		this.player=new LinkedList<String>();
		super.initialize(aContext);
		try {
			this.wordList = IOUtils.readLines(new FileInputStream(String.valueOf(aContext
					.getConfigParameterValue(WORD_PLAYER_PATH))));
			Collections.sort(wordList); // sort collection to make binary search possible
		} catch (IOException e) {
			e.printStackTrace();
			aContext.getLogger().log(Level.SEVERE, "error reading dictionary file");
			throw new ResourceInitializationException(e);
		}
	}


	public void process(JCas jcas) throws AnalysisEngineProcessException {
		List<Annotation> people;
		for(Annotation annotation:jcas.getAnnotationIndex(SentenceAnnotation.type)){
			people=this.getPeopleInSentence(annotation, jcas);
			if(people!=null){
				for(Annotation person:people){
					this.findRole(person, annotation, jcas);
				}
			}

		}
		Collections.sort(this.player);
		for(Annotation annotation:jcas.getAnnotationIndex(PersonAnnotation.type)){
			if(Collections.binarySearch(this.player, annotation.getCoveredText())>=0 && 
					this.position2player.get(annotation.getBegin())==null){
				PlayerAnnotation playerAnnotation=new PlayerAnnotation(jcas);
				playerAnnotation.setBegin(annotation.getBegin());
				playerAnnotation.setEnd(annotation.getEnd());
				playerAnnotation.addToIndexes();
			}
		}
	}

	private void findRole(Annotation people,Annotation sentence,JCas jcas){
		List<Annotation> near=this.findNearToken(people, sentence, jcas);
		String text;
		Type type;
		for(Annotation an:near){
			text=an.getCoveredText();
			type=an.getType();
			if(an.getFeatureValueAsString(type.getFeatureByBaseName(
					POS_FEATURENAME)).length()>2&&
					an.getFeatureValueAsString(type.getFeatureByBaseName(
					POS_FEATURENAME)).substring(0,2).equals("vb")){
				text=an.getCoveredText();
			}
			if(Collections.binarySearch(this.wordList, text)>=0){
				PlayerAnnotation playerAnnotation=new PlayerAnnotation(jcas);
				playerAnnotation.setBegin(people.getBegin());
				playerAnnotation.setEnd(people.getEnd());
				playerAnnotation.addToIndexes();
				this.player.add(people.getCoveredText());
				this.position2player.put(people.getBegin(), people.getCoveredText());
				break;
			}
		}


	}
	private List<Annotation> getPeopleInSentence(Annotation annotation,JCas jcas) {
		List<Annotation> people=new LinkedList<Annotation>();
		for(Annotation a:jcas.getAnnotationIndex(PersonAnnotation.type)){
			if(a.getBegin()>=annotation.getBegin()&&a.getEnd()<=annotation.getEnd()){
				people.add(a);
			}
		}
		if(people.size()==0) people=null;
		return people;
	}

	private List<Annotation> findNearToken(Annotation token,Annotation sentence,JCas jcas){
		List<Annotation> tokens=new LinkedList<Annotation>();
		List<Annotation> results=new LinkedList<Annotation>();
		for(Annotation annotation:jcas.getAnnotationIndex(TokenAnnotation.type)){
			if(annotation.getBegin()>=sentence.getEnd()) break;
			if(annotation.getBegin()>=sentence.getBegin()) tokens.add(annotation);
		}
		int i=0;
		for(Annotation a:tokens){
			if(a.getCoveredText().equals(token.getCoveredText())){
				break;
			}
			i++;
		}
		int j=i-1;
		while(j>=0&&j>i-5){
			results.add(tokens.get(j));
			j--;
		}
		j=i+1;
		while(j<tokens.size()&&j<i+5){
			results.add(tokens.get(j));
			j++;
		}
		return results;
	}
}
